package com.yuma.predicate;

import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;

@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
    public static final String ATTR_KEY = "attr";
    public static final String VALUE_KEY = "value";

    public VipRoutePredicateFactory() {
        super(VipRoutePredicateFactory.Config.class);
    }

    public List<String> shortcutFieldOrder() {
        return Arrays.asList("attr", "value");
    }

    public Predicate<ServerWebExchange> apply(final VipRoutePredicateFactory.Config config) {
        return new GatewayPredicate() {
            public boolean test(ServerWebExchange exchange) {
                if (!StringUtils.hasText(config.getValue())) {
                    return exchange.getRequest().getQueryParams().containsKey(config.attr);
                } else {
                    List<String> values = (List)exchange.getRequest().getQueryParams().get(config.attr);
                    if (values == null) {
                        return false;
                    } else {
                        Iterator var3 = values.iterator();

                        String value;
                        do {
                            if (!var3.hasNext()) {
                                return false;
                            }

                            value = (String)var3.next();
                        } while(value == null || !value.matches(config.getValue()));

                        return true;
                    }
                }
            }

            public Object getConfig() {
                return config;
            }

            public String toString() {
                return String.format("Query: attr=%s value=%s", config.attr, config.value);
            }
        };
    }

    @Validated
    public static class Config {
        private @NotEmpty String attr;
        private String value;

        public Config() {
        }

        public String getAttr() {
            return this.attr;
        }

        public VipRoutePredicateFactory.Config setAttr(String attr) {
            this.attr = attr;
            return this;
        }

        public String getValue() {
            return this.value;
        }

        public VipRoutePredicateFactory.Config setValue(String value) {
            this.value = value;
            return this;
        }
    }

}
